package myJs.user

import myJs.Utils._
import org.scalajs.dom.{Element, _}
import scalatags.Text.{TypedTag, all}
import scalatags.Text.all.{value, _}

import scala.scalajs.js
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import myJs.tool.Tool.{layerOptions, myElement}
import myJs.myPkg.{ColumnOptions, DatepickerOptions, LayerOptions, Swal, SwalOptions, TableOptions}


import scala.scalajs.js.{Date, JSON}
import myJs.myPkg.jquery._
import org.scalajs.dom.ext.Ajax

import scala.concurrent.ExecutionContext.Implicits.global
import myJs.Implicits._
import myJs.tool.Tool
import shared.VarTool

import scala.scalajs.js.JSConverters._
import scala.collection.immutable.SeqMap
import scala.scalajs.js.Dynamic.{global => g}

/**
 * Created by yz on 2019/4/25
 */
@JSExportTopLevel("MissionManage")
object MissionManage {

  val typeTagEmpty = List[TypedTag[String]]()
  val tableId = "missionTable"
  val kind = VarTool.batchMissionStr

  var queryMap = Map[String, String]()
  val timeFieldNames = List("startTime", "endTime")

  @JSExport("init")
  def init = {
    initFilterContent
    initTable
    $("#missionTable").bootstrapTable()
    refreshTable(data => {
      MissionSummary.bindEvt
    })
    updateMissionSocket
    Tool.clickHide
  }

  def tableDataF = {
    val url = g.jsRoutes.controllers.MissionController.getAllMission().url.toString
    Ajax.get(url = s"${url}?kind=${kind}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      xhr.responseText.toJArJDS
    }
  }

  val operateColumn = js.Array(
    ColumnOptions.field("operate").title("操作").formatter(operateFmt).filterControl("clear")
  )

  def tbFmt(columnName: String): js.Function = (v: js.Any, row: js.Dictionary[js.Any]) => columnName match {
    case "missionName" => {
      val state = row("state")
      if (state == "success") {
        val detailUrl = g.jsRoutes.controllers.MissionController.missionSummaryBefore().url.toString
        a(title := "详情", href := s"${detailUrl}?missionId=${row("id")}", cursor.pointer, target := "_blank",
          v.toString
        ).render
      } else v.toString
    }
    case "state" => {
      val state1 = if (List("success").contains(row("state"))) {
        span(cls := "label label-success", "成功 ")
      } else if (List("running").contains(row("state"))) {
        span("正在分析 ",
          img(cls := "runningImage", src := "/assets/images/running2.gif", width := 30, height := 20))
      } else if (List("wait", "preparing").contains(row("state"))) {
        span(
          span(cls := "label label-default", "排队中 "),
          all.raw("&nbsp;"),
          img(cls := "runningImage", src := "/assets/images/running2.gif", width := 30, height := 20))
      } else {
        span(cls := "label label-danger", "错误 ")
      }
      state1.toString()
    }

    case _ => v
  }

  def getFilterSelectHtml(field: String) = {
    select(`type` := "text", filterDataField := field, `class` := s"myFilter filterSelect form-control  search-input", width := "100%")
  }

  def initFilterSelect(fieldNames: List[String]) = {
    fieldNames.foreach { id =>
      $(s"th[data-field='${id}']").append(getFilterSelectHtml(id).render)
    }
  }

  def dateInit = {
    val options = DatepickerOptions.format(Tool.pattern).language("zh-CN").autoclose(true).forceParse(true)
    $(".myDatepicker").datepicker(options)
  }

  def expStyle(columnName: String): js.Function = (v: js.Any, row: js.Dictionary[Any]) => columnName match {
    case "missionIntro" => js.Dictionary("css" -> js.Dictionary(
      "overflow" -> "hidden", "white-space" -> "nowrap", "text-overflow" -> "ellipsis", "max-width" -> "11em",
      "width" -> "12em"
    ))
    case _ => v
  }

  def initTable = {
    val tableId = "missionTable"
    val map = SeqMap("missionName" -> "分析名称", "missionIntro" -> "分析描述", "state" -> "运行状态",
      "startTime" -> "开始日期", "endTime" -> "结束日期")
    val columnNames = map.keyList
    val columns = columnNames.map { columnName =>
      val title = map.getOrElse(columnName, columnName)
      val fmt = MissionManage.tbFmt(columnName)
      val style = expStyle(columnName)
      val basicOptions = ColumnOptions.field(columnName).title(title).sortable(true).formatter(fmt).cellStyle(style)
      val datepickerOptions: js.Dictionary[js.Any] = js.Dictionary("format" -> Tool.pattern, "language" -> "zh-CN",
        "autoclose" -> true)
      columnName match {
        case x if List("missionName", "missionIntro", "state", "startTime", "endTime").contains(x) => basicOptions.
          sortable(false).operateable(true)
        case _ => basicOptions
      }
    }.concat(operateColumn)
    val options = TableOptions.columns(columns.toJSArray).searchOnButton(false).filterControl(false)
    $(s"#${tableId}").bootstrapTable(options)
    initFilter
    //    toggleFilter
  }

  def getFilterInputHtml(field: String) = {
    input(`type` := "text", filterDataField := field, `class` := s"myFilter filterInput form-control  search-input", width := "100%")
  }

  def getFilterSearchHtml(field: String) = {
    span(`class` := "myFilter",
      a(marginLeft := 8, `class` := s"myFilter mySearch",
        onclick := "MissionManage.execFilter", title := "搜索", cursor.pointer,
        filterDataField := "operate",
        span(
          em(cls := "fa fa-search")
        )
      ),
      all.raw("&nbsp;"),
      a(
        title := "清除", filterDataField := "operate", `class` := s"myFilter mySearch",
        cursor.pointer,
        onclick := s"MissionManage.clearFilter",
        span(
          em(cls := "fa fa-trash")
        )
      )
    )
  }

  def initFilterInput(fieldNames: List[String]) = {
    fieldNames.foreach { id =>
      $(s"th[data-field='${id}']").append(getFilterInputHtml(id).render)
    }
  }

  def initFilterStartTime(fieldNames: List[String]) = {
    fieldNames.foreach { id =>
      $(s"th[data-field='${id}']").append(getFilterStartTimeHtml(id).render)
    }
  }

  def initFilterEndTime(fieldNames: List[String]) = {
    fieldNames.foreach { id =>
      $(s"th[data-field='${id}']").append(getFilterEndTimeHtml(id).render)
    }
  }

  def initFilterSearch(fieldNames: List[String]) = {
    fieldNames.foreach { id =>
      $(s"th[data-field='${id}']").append(getFilterSearchHtml(id).render)
    }
  }

  def getFilterEndTimeHtml(field: String) = {
    input(`type` := "text", float := "left", filterDataField := "endTime", readonly,
      `class` := s"myFilter myDatepicker form-control endTime",
      width := "100%", placeholder := s"结束日期")
  }

  def getFilterStartTimeHtml(field: String) = {
    input(`type` := "text", float := "left", filterDataField := "startTime", readonly,
      `class` := s"myFilter myDatepicker form-control startTime",
      width := "100%", placeholder := s"开始日期")
  }

  def initFilter = {
    dateInit
  }

  @JSExport("hideFilterContent")
  def hideFilterContent(y: Element) = {
    val fieldName = Tool.getFilterDataFieldName($(y).parents(".filterContent"))
    val inputY = Tool.getInputByName(fieldName)
    if (timeFieldNames.contains(fieldName)) {
      val fieldNames = List("startTime", "endTime")
      fieldNames.foreach { name =>
        val key = s"${fieldName}.${name}"
        $(y).parents(".filterContent").findInputByName(name).`val`(queryMap.get(key).getOrElse(""))
      }
    } else if ($(inputY).hasClass("valueInput")) {
      val key = s"${fieldName}.${fieldName}"
      Tool.getInputByName(fieldName).`val`(queryMap.get(key).getOrElse(""))
    }
    $(y).parents(".filterContent").hide()
  }

  @JSExport("execSort")
  def execSort(y: Element) = {
    fillSortHtml(y)
    assignQueryMap
    val iJq = $(y).find("i")
    val isAsc = !iJq.hasClass("fa-sort-alpha-desc")
    val order = if (!isAsc) {
      "desc"
    } else "asc"
    val fieldName = Tool.getFilterDataFieldName($(y).parents(".filterContent"))
    val faClass = if (isAsc) "fa-long-arrow-up" else "fa-long-arrow-down"
    $(s"button[filter-data-field=${fieldName}]").find(".afterSortFa")
      .removeClass("fa-long-arrow-up").removeClass("fa-long-arrow-down").
      addClass(faClass)
    $(".myLi").removeClass("active")
    $(y).addClass("active")
    hideFilterContent(y)
    refreshTable()

  }

  def getAscLi = {
    li(`class` := "myLi hasHover", onclick := "MissionManage.execSort(this)",
      span(`class` := "sortFa",
        i(`class` := "fa fa-sort-alpha-asc")
      ),
      span("升序排序")
    )
  }

  def getDescLi = {
    li(`class` := "myLi hasHover", onclick := "MissionManage.execSort(this)",
      span(`class` := "sortFa",
        i(`class` := "fa fa-sort-alpha-desc")
      ),
      span("降序排序")
    )
  }

  def getFooter = {
    div(`class` := "modal-footer bg-info",
      button(`type` := "button", `class` := "btn btn-sm blue", onclick := "MissionManage.confirmFilter(this)",
        "确定"),
      button(`type` := "button", dataDismiss := "modal", `class` := "btn btn-default",
        onclick := "MissionManage.hideFilterContent(this)",
        "关闭")
    )
  }

  def assignQueryMap = {
    val filterMap = $(".filterContent").mapElems(y => y).flatMap { y =>
      val fieldName = Tool.getFilterDataFieldName(y)
      $(y).find(":input.filterInput").mapElems(y => y).map { inY =>
        val name = $(inY).attr("name").toString
        val v = $(inY).myVal
        val finalName = s"${fieldName}.${name}"
        (finalName, v)
      }
    }.toMap
    val eachParent = $("sup.sortSub").parents(".eachFCParent")
    val sortMap = if (eachParent.mapElems(y => y).isEmpty) {
      Map[String, String]()
    } else {
      val order = eachParent.attr("sort-type").toString
      val sort = Tool.getFilterDataFieldName(eachParent)
      Map("sort" -> sort, "order" -> order)
    }
    queryMap = filterMap ++ sortMap
  }

  @JSExport("removeCondition")
  def removeCondition(y: Element) = {
    val fieldName = Tool.getFilterDataFieldName(y)
    if (timeFieldNames.contains(fieldName)) {
      $(s"#${fieldName}Content").findInputByName("startTime").`val`("")
      $(s"#${fieldName}Content").findInputByName("endTime").`val`("")
    } else if (Tool.getInputByName(fieldName).hasClass("valueInput")) {
      Tool.getInputByName(fieldName).`val`("")
    }
    fillConditionHtml
    refreshTable()
  }

  def fillConditionHtml = {
    val textTs = $(".textInput").mapElems { y =>
      val fieldName = $(y).attr("name").toString
      val columnName = $(y).parents(".filterContent").attr("label").toString
      (fieldName, columnName)
    }
    val textConditionHtml = textTs.map { case (fieldName, columnName) =>
      val curV = Tool.getInputByName(fieldName).myVal
      if (curV.isEmpty) {
        ""
      } else {
        span(`class` := "eachFCParent",
          span(`class` := "eachFilterCondition",
            span(s"${columnName} "),
            span(color := "red", "LIKE"),
            s" ${curV}",
          ),
          sup(`class` := "mySup", onclick := "MissionManage.removeCondition(this)", filterDataField := fieldName,
            i(`class` := "fa fa-times-circle")
          )
        ).render

      }
    }.mkString(" ")

    val selectTs = $(".selectInput").mapElems { y =>
      val fieldName = $(y).attr("name").toString
      val columnName = $(y).parents(".filterContent").attr("label").toString
      (fieldName, columnName)
    }
    val selectConditionHtml = selectTs.map { case (fieldName, columnName) =>
      val curV = Tool.getInputByName(fieldName).myVal
      if (curV.isEmpty) {
        ""
      } else {
        span(`class` := "eachFCParent",
          span(`class` := "eachFilterCondition",
            span(s"${columnName} "),
            span(color := "red", "等于"),
            s" ${curV}",
          ),
          sup(`class` := "mySup", onclick := "MissionManage.removeCondition(this)", filterDataField := fieldName,
            i(`class` := "fa fa-times-circle")
          )
        ).render
      }
    }.mkString(" ")

    val timeConditionHtml = $(".filterContent").mapElems(y => y).map { y =>
      val fieldName = Tool.getFilterDataFieldName(y)
      val columnName = $(y).attr("label").toString
      val startTime = $(y).find(":input[name='startTime']").myVal
      val endTime = $(y).find(":input[name='endTime']").myVal
      val trueStartTime = if (startTime.isEmpty) "无" else startTime
      val trueEndTime = if (endTime.isEmpty) "无" else endTime
      val inConditionHtml = if (startTime.isEmpty && endTime.isEmpty) {
        ""
      } else {
        span(`class` := "eachFCParent",
          span(`class` := "eachFilterCondition",
            span(s"${columnName}"),
            s" ${trueStartTime} - ${trueEndTime}",
          ),
          sup(`class` := "mySup", onclick := "MissionManage.removeCondition(this)", filterDataField := s"${fieldName}",
            i(`class` := "fa fa-times-circle")
          )
        ).render
      }
      inConditionHtml
    }.mkString(" ")

    val conditionHtml = List(textConditionHtml, selectConditionHtml, timeConditionHtml).mkString(" ")
    if (conditionHtml.trim.isEmpty) {
      $("#filterCondition").html("")
      $("#filterCondition").parent().hide()
    } else {
      $("#filterCondition").html(conditionHtml)
      $("#filterCondition").parent().show()
    }

  }


  @JSExport("confirmFilter")
  def confirmFilter(y: Element) = {
    assignQueryMap
    hideFilterContent(y)
    fillConditionHtml
    refreshTable()
  }

  def fillSortHtml(y: Element) = {
    val iJq = $(y).find("i")
    val isAsc = !iJq.hasClass("fa-sort-alpha-desc")
    val sortTypeStr = if (isAsc) {
      "asc"
    } else "desc"
    val orderHtml = if (isAsc) {
      span(color := "red", "升序")
    } else span(color := "blue", "降序")
    val filterContentJq = $(y).parents(".filterContent")
    val label = filterContentJq.attr("label").toString
    val fieldName = Tool.getFilterDataFieldName(filterContentJq)
    val conditionHtml = span(`class` := "eachFCParent",
      filterDataField := fieldName, sortType := sortTypeStr,
      span(`class` := "eachFilterCondition",
        span(s"${label} , "),
        orderHtml,
      ),
      sup(`class` := "mySup sortSub", onclick := "MissionManage.removeSort(this)",
        i(`class` := "fa fa-times-circle")
      )
    ).render
    $("#sortCondition").html(conditionHtml)
    $("#sortCondition").parent().show()
  }

  def initFilterContent = {
    case class FilterContentData(fieldName: String, label: String, values: List[String] = List[String]())
    val textSortDatas = List(
      FilterContentData("missionName", "分析名称"),
      FilterContentData("missionIntro", "分析描述")
    )
    val textSortContentHtml = textSortDatas.map { x =>
      div(id := s"${x.fieldName}Content", `class` := "menuContent filterContent", display := "none",
        filterDataField := s"${x.fieldName}", attr("label") := x.label,
        form(`class` := "form-horizontal myForm",
          ul(`class` := "myUl",
            getAscLi,
            getDescLi,
            li(`class` := "myDivider"),
            li(`class` := "myLi",
              div(marginBottom := 10,
                span(`class` := "fa fa-filter"),
                " 文本检索"
              ),
              div(`class` := "form-group",
                div(`class` := "col-sm-12",
                  input(`type` := "text", `class` := "form-control filterInput valueInput textInput",
                    name := x.fieldName, width := "100%")
                )
              )
            ),
          )
        ),
        getFooter
      )
    }.mkString("&nbsp;")
    val sortDatas = List(
      FilterContentData("state", "运行状态", List("", "成功", "失败", "运行中"))
    )
    val selectSortContentHtml = sortDatas.map { x =>
      div(id := s"${x.fieldName}Content", `class` := "menuContent filterContent",
        display := "none",
        filterDataField := s"${x.fieldName}", attr("label") := x.label,
        form(`class` := "form-horizontal myForm",
          ul(`class` := "myUl",
            getAscLi,
            getDescLi,
            li(`class` := "myDivider"),
            li(`class` := "myLi",
              div(marginBottom := 10,
                span(`class` := "fa fa-filter"),
                " 条件检索(单选)"
              ),
              div(`class` := "form-group", marginBottom := 10,
                div(`class` := "col-sm-12",
                  select(`type` := "text", `class` := "form-control filterInput valueInput selectInput",
                    name := x.fieldName, width := "100%",
                    x.values.map { v =>
                      option(value := v, v)
                    }
                  )
                )
              ),
            ),
          )
        ),
        getFooter
      )
    }.mkString("&nbsp;")

    val timeSortDatas = List(
      FilterContentData("startTime", "开始日期"),
      FilterContentData("endTime", "结束日期")
    )

    val timeSortContentHtml = timeSortDatas.map { x =>
      div(id := s"${x.fieldName}Content", `class` := "menuContent filterContent",
        display := "none",
        filterDataField := s"${x.fieldName}", attr("label") := x.label,
        form(`class` := "form-horizontal myForm",
          ul(`class` := "myUl",
            getAscLi,
            getDescLi,
            li(`class` := "myDivider"),
            li(`class` := "myLi",
              div(marginBottom := 10,
                span(`class` := "fa fa-filter"),
                " 日期检索"
              ),
              div(`class` := "form-group", marginBottom := 10,
                div(`class` := "col-sm-12",
                  input(`type` := "text", `class` := "filterInput myDatepicker form-control startTime",
                    name := "startTime", width := "100%", placeholder := "起始", readonly)
                )
              ),
              div(`class` := "form-group",
                div(`class` := "col-sm-12",
                  input(`type` := "text", `class` := "filterInput myDatepicker form-control endTime",
                    name := "endTime", width := "100%", placeholder := "终止", readonly)
                )
              ),
            ),
          )
        ),
        getFooter
      )
    }.mkString("&nbsp;")

    val contentHtml = List(textSortContentHtml, selectSortContentHtml, timeSortContentHtml).mkString("&nbsp;")
    $("#allFilterContent").html(contentHtml)

  }

  @JSExport("clearFilter")
  def clearFilter = {
    clearInput
    execFilter
  }

  @JSExport("execFilter")
  def execFilter = {
    fillConditionHtml
    refreshTable()
  }

  def clearInput = {
    $(".filterInput").not(".select2Input").`val`("")
  }

  @JSExport("toggleFilter")
  def toggleFilter = {
    val filterNonExist = $(".myFilter").css("display") == "none"
    if (filterNonExist) {
      $(".myFilter").show()
    } else {
      $(".myFilter").hide()
    }
  }

  def refreshTable(f: JArJDS => js.Any = (myData) => ()) = {
    assignQueryMap
    println(queryMap)
    tableDataF.map { data =>
      val sortOp = queryMap.get("sort")
      val sortData = sortOp.map { sort =>
        queryMap("order") match {
          case "desc" =>
            data.sortBy(_ (sort)).reverse
          case "asc" => data.sortBy(_ (sort))
        }
      }.getOrElse(data)

      val stateMap = Map("" -> "", "成功" -> "success", "失败" -> "error", "运行中" -> "running")

      def loopFilter(sortData: JArJDS) = {

        val filterColumns = queryMap.removedAll(List("sort", "order")).filter(_._2.trim.nonEmpty).keyList

        def loop(acc: JArJDS, elems: List[String]): JArJDS = {
          elems match {
            case Nil => acc
            case y :: ys =>
              val searchV = queryMap(y)
              val trueSearchV = if (y == "state") stateMap(searchV) else searchV
              val fieldName = y.split("\\.")(0)
              val name = y.split("\\.")(1)
              val curFilterData = if (timeFieldNames.contains(fieldName)) {
                acc.filter { row =>
                  val dbDate = row(fieldName)
                  if (name == "startTime") {
                    timeBefore(trueSearchV, dbDate)
                  } else {
                    timeAfter(trueSearchV, dbDate)
                  }
                }
              } else {
                acc.filter { row =>
                  row(fieldName).contains(trueSearchV)
                }
              }
              loop(curFilterData, ys)
          }
        }

        loop(sortData, filterColumns)
      }

      val filterData = loopFilter(sortData)
      $(s"#${tableId}").bootstrapTable("load", filterData)
      f(data)
    }
  }

  def timeBefore = (dateStr: String, dbDateStr: String) => {
    val date = new Date(dateStr)
    val dbDate = new Date(dbDateStr)
    dbDate.setUTCHours(0, 0, 0, 0)
    date.getTime() <= dbDate.getTime()
  }

  def timeAfter = (dateStr: String, dbDateStr: String) => {
    val date = new Date(dateStr)
    val dbDate = new Date(dbDateStr)
    dbDate.setUTCHours(0, 0, 0, 0)
    date.getTime() >= dbDate.getTime()
  }

  @JSExport("operateFmt")
  def operateFmt: js.Function = {
    (v: js.Any, row: js.Dictionary[js.Any]) =>
      val deleteStr = a(
        title := "删除",
        cursor.pointer,
        onclick := s"MissionManage.deleteData('" + row("id") + "')",
        target := "_blank",
        span(
          em(cls := "fa fa-close")
        )
      )

      val viewStr = a(title := "日志", onclick := s"MissionManage.viewLog('${row("id")}')", cursor.pointer,
        span(em(cls := "fa fa-file-text"))
      )

      val state2 = if (List("success", "error").contains(row("state"))) {
        List(viewStr)
      } else List[TypedTag[String]]()
      val rs = state2 ::: List(deleteStr)
      rs.mkString("&nbsp;")

  }

  @JSExport("removeSort")
  def removeSort(y: Element) = {
    val fieldName = Tool.getFilterDataFieldName($(y).parents(".eachFCParent"))
    $("#sortCondition").html("")
    $("#sortCondition").parent().hide()
    $(s"button[filter-data-field=${fieldName}]").find(".afterSortFa").
      removeClass("fa-long-arrow-up").removeClass("fa-long-arrow-down")
    $(".myLi").removeClass("active")
    refreshTable()
  }

  @JSExport("search")
  def search = {
    val parentStr = "#search"
    val data = $(s"${parentStr} #form").serialize()
    val formData = new FormData($(s"${parentStr} #form")(0).toHTMLFormElement)
    val url = g.jsRoutes.controllers.MissionController.search().url.toString
    val index = layer.alert(Tool.myElement, layerOptions)
    Ajax.post(url = s"${url}", data = formData, responseType = "application/json").map { xhr =>
      val rs = xhr.responseText.toJArJDS
      $(s"#${tableId}").bootstrapTable("destroy").bootstrapTable(TableOptions.data(rs))
      layer.close(index)
    }
  }

  @JSExport("viewLog")
  def viewLog(id: String) = {
    val url = g.jsRoutes.controllers.MissionController.getLogContent().url.toString
    Ajax.get(url = s"${url}?missionId=${id}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val dict = xhr.responseText.toJDS
      val options = LayerOptions.`type`(1).title("<h4>运行信息</h4>").area(js.Array("900px", "600px")).
        skin("layui-layer-demo").closeBtn(1).anim(2).shadeClose(true).maxmin(true).
        content(s"<pre style='word-wrap: break-word' class='genome-pre'>${dict("str")}</pre>")
      layer.open(options)
    }
  }

  @JSExport("deleteData")
  def deleteData(id: String) = {
    val options = SwalOptions.title("").text("确定要删除此数据吗？").`type`("warning").showCancelButton(true).
      showConfirmButton(true).confirmButtonClass(Tool.confirmButtonClass).confirmButtonText("确定").closeOnConfirm(false).
      cancelButtonText("取消").showLoaderOnConfirm(true).cancelButtonClass(Tool.cancelButtonClass)
    Swal.swal(options, () => {
      val url = g.jsRoutes.controllers.MissionController.deleteMissionById().url.toString
      Ajax.delete(url = s"${url}?missionId=${id}").map { xhr =>
        refreshTable { data =>
          Swal.swal(SwalOptions.title("成功").text("删除成功").`type`("success"))
        }
      }
    })
  }

  def updateMissionSocket = {
    val url = g.jsRoutes.controllers.MissionController.updateMissionSocket(kind).url.toString
    val wsUri = s"ws://${window.location.host}${url}"
    webSocket(wsUri)
  }

  def webSocket(wsUri: String) = {
    val websocket = new WebSocket(wsUri)
    websocket.onopen = (evt) =>
      websocket.send(JSON.stringify(js.Dictionary("info" -> "start")))
    websocket.onclose = (evt) =>
      println(s"ERROR:${evt.code},${evt.reason},${evt.wasClean}")
    websocket.onmessage = (evt) => {
      val message = evt.data
      val data = JSON.parse(message.toString).toJArJDS
      $("#missionTable").bootstrapTable("load", data)
    }
    websocket.onerror = (evt) => {
      updateByHand
      println(s"ERROR:${evt.toString}")
    }
  }

  def updateByHand = {
    js.timers.setInterval(3000) {
      refreshTable()
    }
  }


}
